From 2580424cce5e407dc62d25f06ac74ff10fb5d149 Mon Sep 17 00:00:00 2001 From: Shan Haitao Date: Tue, 19 Jul 2011 08:24:19 +0100 Subject: [PATCH] Adding back guest MSI eoi support for unmaskable MSI interrupt This patch adds back proper guest MSI EOI hook for correctly handling unmaskable MSI interrupt, which is wrongly removed by changset 23703. Signed-off-by: Shan Haitao --- xen/arch/x86/hvm/vlapic.c | 2 ++ xen/drivers/passthrough/io.c | 58 ++++++++++++++++++++++++++++++++++++ xen/include/asm-x86/hvm/io.h | 1 + 3 files changed, 61 insertions(+) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index fabe0e91e8..8b05f1adc3 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -400,6 +400,8 @@ void vlapic_EOI_set(struct vlapic *vlapic) if ( vlapic_test_and_clear_vector(vector, &vlapic->regs->data[APIC_TMR]) ) vioapic_update_EOI(vlapic_domain(vlapic), vector); + + hvm_dpci_msi_eoi(current->domain, vector); } int vlapic_ipi( diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c index bce86adafc..44c89365b4 100644 --- a/xen/drivers/passthrough/io.c +++ b/xen/drivers/passthrough/io.c @@ -421,6 +421,56 @@ int hvm_do_IRQ_dpci(struct domain *d, struct pirq *pirq) } #ifdef SUPPORT_MSI_REMAPPING +/* called with d->event_lock held */ +static void __msi_pirq_eoi(struct hvm_pirq_dpci *pirq_dpci) +{ + irq_desc_t *desc; + + if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MAPPED) && + (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) ) + { + struct pirq *pirq = dpci_pirq(pirq_dpci); + + BUG_ON(!local_irq_is_enabled()); + desc = pirq_spin_lock_irq_desc(pirq, NULL); + if ( !desc ) + return; + desc_guest_eoi(desc, pirq); + } +} + +static int _hvm_dpci_msi_eoi(struct domain *d, + struct hvm_pirq_dpci *pirq_dpci, void *arg) +{ + int vector = (long)arg; + + if ( (pirq_dpci->flags & HVM_IRQ_DPCI_MACH_MSI) && + (pirq_dpci->gmsi.gvec == vector) ) + { + int dest = pirq_dpci->gmsi.gflags & VMSI_DEST_ID_MASK; + int dest_mode = !!(pirq_dpci->gmsi.gflags & VMSI_DM_MASK); + + if ( vlapic_match_dest(vcpu_vlapic(current), NULL, 0, dest, + dest_mode) ) + { + __msi_pirq_eoi(pirq_dpci); + return 1; + } + } + + return 0; +} + +void hvm_dpci_msi_eoi(struct domain *d, int vector) +{ + if ( !iommu_enabled || !d->arch.hvm_domain.irq.dpci ) + return; + + spin_lock(&d->event_lock); + pt_pirq_iterate(d, _hvm_dpci_msi_eoi, (void *)(long)vector); + spin_unlock(&d->event_lock); +} + static int hvm_pci_msi_assert(struct domain *d, struct hvm_pirq_dpci *pirq_dpci) { @@ -458,6 +508,14 @@ static int _hvm_dirq_assist(struct domain *d, struct hvm_pirq_dpci *pirq_dpci, else hvm_pci_intx_assert(d, device, intx); pirq_dpci->pending++; + +#ifdef SUPPORT_MSI_REMAPPING + if ( pirq_dpci->flags & HVM_IRQ_DPCI_TRANSLATE ) + { + /* for translated MSI to INTx interrupt, eoi as early as possible */ + __msi_pirq_eoi(pirq_dpci); + } +#endif } /* diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 419f25f41f..ce2bcb373f 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -139,5 +139,6 @@ struct hvm_hw_stdvga { void stdvga_init(struct domain *d); void stdvga_deinit(struct domain *d); +extern void hvm_dpci_msi_eoi(struct domain *d, int vector); #endif /* __ASM_X86_HVM_IO_H__ */ -- 2.30.2